#include <p18f2520.h>

#include <usart.h>

#include <stdio.h>

#include <stdlib.h>

#include "main.h"
#include "afcProtocol.h"
#include "serial.h"
#include "ds18x20.h"

// Static variables
static char cSerialInputBuffer[SERIAL_MAX_BUFFER_LEN];
static int cSerialPtrIn = 0, cSerialPtrOut = 0;

// reception interrupt processing
void vSerialReceive(void)
{
char ptr;

    // Store received char into input buffer
    cSerialInputBuffer[cSerialPtrIn] = RCREG;

    // Compute next location
    ptr = cSerialPtrIn + 1;

    // If pointer arrives at the end of buffer, go to beginning
    if(ptr >= SERIAL_MAX_BUFFER_LEN)
        {
        ptr = 0;
        }

    // Ensure that no pertinent data will be lost
    if(ptr != cSerialPtrOut)
        {
        cSerialPtrIn = ptr;
        }
}

void vSerialGetAndAnalyze(structAFC *stAFC)
{
    char c;

    // If buffer is not empty (input pointer != output pointer)
    if(cSerialPtrIn != cSerialPtrOut)
    {
        // Extract char from buffer
        c = cSerialInputBuffer[cSerialPtrOut];

        // Set output pointer to next position
        cSerialPtrOut++;

        // If pointer arrives at the end of buffer, go to beginning
        if(cSerialPtrOut >= SERIAL_MAX_BUFFER_LEN)
            {
            cSerialPtrOut = 0;
            }

        // Process data
        vRs232dataProcess(c, stAFC);
    }
}

void vRs232dataProcess(char c, structAFC *stAFC)
{
int data;

switch(stAFC->iMode)
		{
		case MODEMANU:
			switch(c)
				{
				case '>':	// Mode astrarm
					stAFC->iMode = MODEASTRARM;
					vInitRs232AfcReceive();
					break;
				case 'h':	// help
                    fprintf(_H_USART,"\r\nMODES :\r\n '>' : AstrARM\r\n 'h' : Help\r\n");
					fprintf(_H_USART,"\r\nAFC command set :\r\n");
					fprintf(_H_USART," >AFC:POS?   => returns position in coder step\r\n");
					fprintf(_H_USART," >AFC:VER?   => returns AFC software version\r\n");
					fprintf(_H_USART," >AFC:MOT?   => returns the current motor type\r\n");
					fprintf(_H_USART," >AFC:UNT?   => returns the current unit\r\n");

					break;
				case 's':	// stop motor
					vStopMotor();
					break;
				default : break;
				}
			break;
		case MODEASTRARM:
			stAFC->iMessageCode = iRs232AfcProcess(c, &data);
			switch(stAFC->iMessageCode)
				{
				case WAITFORMSG : break;
				case WRONGIFCODE :
					vResetMsgStatus();
					break;
				case POSREQUEST :
					PORTBbits.RB6 = !PORTBbits.RB6;
					fprintf(_H_USART,">AFC:POS:%i!",stAFC->iCurrentPosition);
					vResetMsgStatus();
					break;
				case VERSIONREQUEST :
					fprintf(_H_USART,">AFC:VER:%i!",AFCVERSION);
					vResetMsgStatus();
					break;
				case MOTYPEREQUEST :
					fprintf(_H_USART,">AFC:MOT:%i!",stAFC->iMotorType);
					vResetMsgStatus();
					break;
				case UNITREQUEST :
					fprintf(_H_USART,">AFC:UNT:%i!",stAFC->iUnits);
					vResetMsgStatus();
					break;
                case SETPOSITION :
                    fprintf(_H_USART,">AFC:SET:%i!", stAFC->iTargetPosition);
                    vResetMsgStatus();
                    break;
                case TEMPREQUEST :
                    fprintf(_H_USART,">AFC:TMP:%i!",stAFC->iCurrentTemperature);
                    if(stAFC->iIsRunning == 0)
                        {
                            INTCONbits.TMR0IE = 0;
                            stAFC->iCurrentTemperature = iDs18x20GetTemp();
                            INTCONbits.TMR0IE = 1;
                        }
                    vResetMsgStatus();
                    break;
				default :
					vResetMsgStatus();
					break;
				}
			break;
		default : stAFC->iMode = MODEMANU;
			break;
		}
}
